#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/workqueue.h>
#include <linux/slab.h>

MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Workqueue with parameter passing example");

#define WORK_COUNT 3

// 自定义工作数据结构
struct my_work_data {
    struct work_struct work;   // 嵌套工作结构体
    int id;                    // 自定义参数
    char msg[64];              // 可携带字符串
};

// 工作处理函数
static void work_handler(struct work_struct *work)
{
    // 使用 container_of 获取原始结构体指针  此处是进阶用法，用container_of带参数
    struct my_work_data *my_data = container_of(work, struct my_work_data, work);

    // 打印参数
    printk(KERN_INFO "[workqueue] Task ID: %d, Msg: %s\n", my_data->id, my_data->msg);

    // 释放申请的结构体内存
    kfree(my_data);
}

static struct workqueue_struct *my_wq;

static int __init workqueue_param_init(void)
{
    int i;
    printk(KERN_INFO "Workqueue param module loaded.\n");

    // 创建自定义工作队列
    my_wq = create_workqueue("my_param_wq");

    // 创建多个任务
    for (i = 0; i < WORK_COUNT; i++) {
        struct my_work_data *data;

        data = kmalloc(sizeof(struct my_work_data), GFP_KERNEL);
        if (!data) {
            printk(KERN_ERR "Failed to allocate work data\n");
            continue;
        }

        data->id = i;
        snprintf(data->msg, sizeof(data->msg), "Message from task #%d", i);

        INIT_WORK(&data->work, work_handler);
        queue_work(my_wq, &data->work);
    }

    return 0;
}

static void __exit workqueue_param_exit(void)
{
    if (my_wq) {
        flush_workqueue(my_wq);       // 等待所有任务完成
        destroy_workqueue(my_wq);     // 销毁队列
    }

    printk(KERN_INFO "Workqueue param module unloaded.\n");
}

module_init(workqueue_param_init);
module_exit(workqueue_param_exit);